package com.aspire.nm.component.miniServer.status;


import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang3.StringUtils;

import com.aspire.nm.component.commonUtil.constants.ConstantConfig;
import com.aspire.nm.component.commonUtil.date.DateUtil;
import com.aspire.nm.component.miniServer.Controll;
import com.aspire.nm.component.miniServer.annotation.Controller;
import com.aspire.nm.component.miniServer.annotation.Controller.MethodType;
import com.aspire.nm.component.miniServer.annotation.cls.Controllers;
import com.aspire.nm.component.miniServer.protocol.Request;
import com.aspire.nm.component.miniServer.protocol.Response;


public class StatusInfo {

    
    public StatusInfo(int serverPort){
        recentlyStartTime = DateUtil.getCurDateTimeFormat("yy/MM/dd HH:mm:ss");
        Apath apath = new Apath();
        apath.setPath("http://{ip}:"+serverPort);
        apath.setDesc("管理页面(当前页)");
        apath.setMethodInfo("-");
        apath.setGetPost("BOTH");
        path_map.put("-", apath);
    }
    
    
    private LinkedHashMap<String, Apath> path_map =  new LinkedHashMap<String,Apath>();
    
    private String recentlyStartTime;
    public String getRecentlyStartTime() {
        return recentlyStartTime;
    }
    public void setRecentlyStartTime(String recentlyStartTime) {
        this.recentlyStartTime = recentlyStartTime;
    }
    private AtomicLong accecp_count = new AtomicLong(0);//serverSocket.accept();
    private AtomicLong close_count = new AtomicLong(0);//最终close
    
    private AtomicLong client_close_count = new AtomicLong(0);
    private AtomicLong timeout_close_count = new AtomicLong(0);
    
    private AtomicLong reject_close_count = new AtomicLong(0);
    
    private AtomicLong client_close_when_excute_count = new AtomicLong(0);
    
    private AtomicLong process_count = new AtomicLong(0);
    
    private AtomicLong count_401 = new AtomicLong(0);
    private AtomicLong count_403 = new AtomicLong(0);
    private AtomicLong count_404 = new AtomicLong(0);
    private AtomicLong count_500 = new AtomicLong(0);
    private AtomicLong count_504 = new AtomicLong(0);
    
    
    
    
    public LinkedHashMap  <String, Apath> getPath_map() {
        return path_map;
    }
    public void setPath_map(LinkedHashMap<String, Apath> path_map) {
    
        this.path_map = path_map;
    }
    public void clientCloseWhenExcute(){
        client_close_when_excute_count.incrementAndGet();
    }
    public void accecp(){
        accecp_count.incrementAndGet();
    }
    public void clientClose(){
        client_close_count.incrementAndGet();
    }
    public void timeoutClose(){
        timeout_close_count.incrementAndGet();
    }
    public void rejectClose(){
        reject_close_count.incrementAndGet();
    }
    public void close(){
        close_count.incrementAndGet();
    }
    public void process(Request request,Response response,long last,String routingMethodKey){
        if(request.getPath() == null || request.getPath().equals("")){
            routingMethodKey = "-";
        }
        Apath apath = null;
        if(!StringUtils.isEmpty(routingMethodKey)){
            apath = path_map.get(routingMethodKey);
        }
        
        if(response.getHttpRespStatus() == 401){
            count_401.incrementAndGet();
        }
        if(response.getHttpRespStatus() == 403){
            count_403.incrementAndGet();
            if(apath != null)
            apath.getCount_403().incrementAndGet();
        }
        if(response.getHttpRespStatus() == 404){
            count_404.incrementAndGet();
            if(apath != null)
            apath.getCount_404().incrementAndGet();
        }
        if(response.getHttpRespStatus() == 500){
            count_500.incrementAndGet();
            if(apath != null)
            apath.getCount_500().incrementAndGet();
        }
        if(response.getHttpRespStatus() == 504){
            count_504.incrementAndGet();
            if(apath != null)
            apath.getCount_504().incrementAndGet();
        }
        if(response.getHttpRespStatus() == 200 || response.getHttpRespStatus() == 302){
            if(apath != null){
                apath.getCount_200().incrementAndGet();
                apath.getLast_200().addAndGet(last);
            }
        }
        
        process_count.incrementAndGet();
        if(apath != null)
        apath.getCount().incrementAndGet();
    }
    
    
    
    
    
    
    
    
    
    public long getCurrentConn(){
        return accecp_count.longValue() - close_count.longValue(); 
    }
    
    public long getClient_close_when_excute_count(){
        return client_close_when_excute_count.longValue();
    }
    public long getTimeout_close_count() {
        return timeout_close_count.longValue();
    }
    public long getReject_close_count() {
        return reject_close_count.longValue();
    }
    public long getClient_close_count() {
        return client_close_count.longValue();
    }
    public long getProcess_count() {
        return process_count.longValue();
    }
    public AtomicLong getCount_401() {
        return count_401;
    }
    
    public AtomicLong getCount_403() {
        return count_403;
    }
    
    public AtomicLong getCount_404() {
        return count_404;
    }
    public AtomicLong getCount_500() {
        return count_500;
    }
    public AtomicLong getCount_504() {
        return count_504;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    public void init(List<Controll> controllImpls,int serverPort,String annotationValueConfigFile){
        for(Controll controllImpl : controllImpls){
            Controllers annotation_c = controllImpl.getClass().getAnnotation(Controllers.class);
            Method[] methods = controllImpl.getClass().getDeclaredMethods();
            for(Method method:methods){
                if (method.isAnnotationPresent(Controller.class)) {
                    Controller annotation = method.getAnnotation(Controller.class);
                    
                    String methodName = method.getName();
                    String pathPattern = annotation.pathPattern();
                    int cacheTime = annotation.cacheTime();
                    String desc = annotation.desc();
                    int timeout = annotation.timeOut();
                    if(timeout == 0 && annotation_c != null){
                        timeout = annotation_c.timeOut();
                    }
                    String methodType = annotation_c==null?"BOTH":annotation_c.methodType().toString();
                    MethodType methodType_m = annotation.methodType();
                    if(methodType_m != MethodType.FOLLOW){
                        methodType = methodType_m.toString();
                    }
                    
                    
                    Apath apath = new Apath();
                    pathPattern = StringUtils.isEmpty(pathPattern)?methodName:pathPattern;
                    String pathPrefix = "";
                    if(annotation_c != null){
                        pathPrefix = annotation_c.path();
                        if(pathPrefix.startsWith("$")){
                            pathPrefix = ConstantConfig.getPropertiesValue(annotationValueConfigFile, pathPrefix.substring(1));
                        }
                    }
                    pathPattern = "http://{ip}:"+serverPort+"/<br/>"+pathPrefix+pathPattern;
                    apath.setPath(pathPattern);
                    if(cacheTime != 0){
                        apath.setCacheTime(String.valueOf(cacheTime));
                    }
                    if(timeout != 0){
                        apath.setTimeOut(String.valueOf(timeout));
                    }
                    if(annotation_c != null && !annotation_c.allowIpsPattern().equals("")){
                        String allowIpsPattern = annotation_c.allowIpsPattern();
                        if(allowIpsPattern.startsWith("$")){
                            allowIpsPattern = ConstantConfig.getPropertiesValue(annotationValueConfigFile, allowIpsPattern.substring(1));
                        }
                        apath.setAllowsIps(allowIpsPattern.replaceAll("\\|", "\\|<br/>"));
                    }
                    apath.setDesc(desc);
                    apath.setMethodInfo(RoutingMethodKey.getMethodInfo(method,true));
                    apath.setGetPost(methodType);
                    
                    path_map.put(RoutingMethodKey.getMethodInfo(method,false), apath);
                    
                }
            }
        }
    }
}
